﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Midapex.SmartOrm.Tools.Wizard.Properties;
using System.Diagnostics;
using System.Reflection;
using System.Threading;

namespace Midapex.SmartOrm.Tools.Wizard
{
    public partial class OrmTablesControl : UserControl
    {
        public OrmTablesControl()
        {
            InitializeComponent();
            this.typesTree.Visible = false;
            panel1.Visible = false;
        }

        void SetProgressInfo(string info)
        {
            this.infoLabel.Text = info;
            this.infoLabel.Update();
            Thread.Sleep(20);
            this.progressBar.Update();
        }

        internal void UpdateOrmClasses()
        {
            ShowInfoFace(true);
           
            foreach (Assembly a in OrmWizard.OrmAssemblies)
            {
                SetProgressInfo(Resources.LoadAssemby + a.GetName().Name);
                EntityClassesFactory.Instance().LoadEntityClasses(a);
            }
            
            progressBar.Value = 10;
            
            int count = EntityClassesFactory.Instance().EntityClasses.Count;

            if(count==0)
            {
                throw new Exception("not find entity class");
            }

            int step = 90 / count;

            TreeNode root = typesTree.Nodes[0];
            root.Nodes.Clear();
            using (OrmSession session = OrmSessionsFactory.CreateSession())
            {
                foreach (KeyValuePair<string, Type> t in EntityClassesFactory.Instance().EntityClasses)
                {
                    progressBar.Value += step;
                    SetProgressInfo(Resources.LoadType + t.Value.FullName);

                    string className = string.Format("{0}", t.Value.FullName);
                    TreeNode classNode = new TreeNode(className, 1, 1);

                    classNode.Tag = t.Value;

                    root.Nodes.Add(classNode);
                    Table table = EntityClassesFactory.Instance().GetTableByType(t.Value);

                    TreeNode tableNode = new TreeNode(table.Name, 2, 2);

                    if (session.IsTableExist(table))
                    {
                        tableNode = new TreeNode(table.Name, 2, 2);
                    }
                    else
                    {
                        tableNode = new TreeNode(table.Name, 8, 8);
                    }

                    foreach (Column column in table.Columns)
                    {
                        TreeNode columnNode = new TreeNode(column.Name, 3, 3);
                        tableNode.Nodes.Add(columnNode);
                    }

                    classNode.Nodes.Add(tableNode);

                    foreach (Table singleValueTable in table.SinglevaluedRelationTables)
                    {
                        int imageIndex;

                        if (session.IsTableExist(singleValueTable))
                        {
                            imageIndex = 4;
                        }
                        else
                        {
                            imageIndex = 5;
                        }

                        TreeNode singleValueTableNode = new TreeNode(singleValueTable.Name, imageIndex, imageIndex);
                        classNode.Nodes.Add(singleValueTableNode);
                        foreach (Column column in singleValueTable.Columns)
                        {
                            TreeNode columnNode = new TreeNode(column.Name, 3, 3);
                            singleValueTableNode.Nodes.Add(columnNode);
                        }
                    }

                    foreach (Table multiValueTable in table.MultivaluedRelationTables)
                    {
                        int imageIndex;

                        if (session.IsTableExist(multiValueTable))
                        {
                            imageIndex = 4;
                        }
                        else
                        {
                            imageIndex = 5;
                        }

                        TreeNode multiValueTableNode = new TreeNode(multiValueTable.Name, imageIndex, imageIndex);

                        classNode.Nodes.Add(multiValueTableNode);
                        foreach (Column column in multiValueTable.Columns)
                        {
                            TreeNode columnNode = new TreeNode(column.Name, 3, 3);
                            multiValueTableNode.Nodes.Add(columnNode);
                        }
                    }
                }
            }
            root.Expand();
            ShowInfoFace(false);
        }

        void ShowInfoFace(bool showInfo)
        {
            if(showInfo)
            {
                this.typesTree.Visible = false;
                panel1.Visible = false;
                this.progressBar.Visible = true;
                this.infoLabel.Visible = true;
                this.progressBar.Value = 0;
            }
            else
            {
                this.typesTree.Visible = true;
                panel1.Visible = true;
                this.progressBar.Visible = false;
                this.infoLabel.Visible = false;
            }
            
        }
        private void linkLabelRebuildTables_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (MessageBox.Show(this, Resources.BuildAllTablesTip, Resources.Warning,
                MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                ShowInfoFace(true);
                try
                {
                    CreateAllTables();
                }
                catch(Exception ex)
                {
                    MessageBox.Show(this, ex.Message, Resources.Error,
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                ShowInfoFace(false);
            }
        }

        private void CreateAllTables()
        {
            using (OrmSession session = OrmSessionsFactory.CreateSession())
            {

                int step = 100 / EntityClassesFactory.Instance().EntityClassesTables.Count;

                foreach (KeyValuePair<Type, Table> item in EntityClassesFactory.Instance().EntityClassesTables)
                {
                    try
                    {
                        progressBar.Value += step;
                        SetProgressInfo(string.Format("{0}{2}<-{1}", Resources.CreateTable,
                            item.Key.FullName, item.Value.Name));
                        if (session.IsTableExist(item.Value))
                            session.DeleteTable(item.Value);
                        session.CreateTable(item.Value);
                    }
                    catch (Exception ex)
                    {
                        throw new OrmRuntimeException(ex.Message + Resources.DeleteTablesByDbTools);
                    }
                }
            }
      
            UpdateOrmClasses();

            MessageBox.Show(this, Resources.CreateTableSuccess, Resources.Information,
                MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        private void linkLabelExpandAll_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            typesTree.Nodes[0].ExpandAll();
        }

        private void linkLabelCollapseAll_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            typesTree.Nodes[0].Collapse();
        }

        private void linkLabelBuildTable_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            TreeNode node = typesTree.SelectedNode;

            if(node!=null && node.Tag !=null )
            {
                Type type = node.Tag as Type;
                Debug.Assert(type != null);

                string info = string.Format(Resources.BuildTableTip,type.ToString());

                if (MessageBox.Show(this, info, Resources.Warning,
               MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                {
                    using (OrmSession session = OrmSessionsFactory.CreateSession())
                    {
                        if (session.IsTableExist(type))
                        {
                            session.DeleteTable(type);
                        }
                        session.CreateTable(node.Tag as Type);
                    }
                    UpdateOrmClasses();
                    MessageBox.Show(this, Resources.CreateTableSuccess, Resources.Information,
                   MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            else
            {
                MessageBox.Show(this, Resources.SelectOrmTypeFirst, Resources.Warning, 
                    MessageBoxButtons.OK, MessageBoxIcon.Hand);
            }
        }
    }
}
